/**
 * 国际化的时间工具
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat
 * {
		const date = new Date(value) // 将时间戳转换为Date对象
		const options = { year: 'numeric', month: 'long', day: 'numeric' } // 定义日期格式
		return new Intl.DateTimeFormat('zh-CN', options).format(date) // 使用Intl.DateTimeFormat进行格式化
	}
 */

/**
 * 获取对应的时间结果
 * type：返回值格式：timestamp、string、date
 */
const getResult = (params, type = 'timestamp') => {
	switch (type){
		case 'timestamp':
			return getTimestamp(params)
		case 'string':
			return getString(params)
		case 'date':
			return dateFromOther(params)
		default:
			break;
	}
}

/**
 * 字符串、时间戳转时间对象
 * result 该时间的具体年月日时分秒毫秒周
 */
const dateFromOther = (date = new Date(), result) => {
	if (typeof(date) === 'string') {
		// 时间日期字符串
		if (date.indexOf(' ') === -1) {
			date += ' ' + '00:00:00'
		}
		date = new Date(date)
	} else if (typeof(date) == 'number') {
		// 时间戳
		date = new Date(date)
	}
	if (result) {
		let year = date.getFullYear(),
			month = date.getMonth() + 1,
			day = date.getDate(),
			hour = date.getHours(),
			minute = date.getMinutes(),
			second = date.getSeconds(),
			msec = date.getMilliseconds(),
			week = date.getDay()
		year = year.toString()
		if (month < 10) {
			month = '0' + month
		} else {
			month = month.toString()
		}
		if (day < 10) {
			day = '0' + day
		} else {
			day = day.toString()
		}
		if (hour < 10) {
			hour = '0' + hour
		} else {
			hour = hour.toString()
		}
		if (minute < 10) {
			minute = '0' + minute
		} else {
			minute = minute.toString()
		}
		if (second < 10) {
			second = '0' + second
		} else {
			second = second.toString()
		}
		if (msec < 10) {
			msec = '00' + msec
		} else if (msec < 100) {
			msec = '0' + msec
		} else {
			msec = msec.toString()
		}
		result.year = year
		result.month = month
		result.day = day
		result.hour = hour
		result.minute = minute
		result.second = second
		result.msec = msec
		result.week = week
	}
	return date
}

/**
 * 得到标准的时间字符串
 * params：时间字符串、时间戳、时间对象
 * symbol：年月日的连接符号
 * 
 * type:
 * 0：年月日时分秒
 * 1：年月日
 * 2：时分秒
 * 3：月日时分
 * 4：年月日时分秒毫秒
 * 5：年月日时分
 * 6：时分
 * 7：年月
 */
const getString = (params = new Date(), type = 0, symbol = '/') => {
	if (params) {
		const result = {}
		const date = dateFromOther(params, result)
		const {year, month, day, hour, minute, second, msec} = result
		if (type === 0) {
			return year + symbol + month + symbol + day + ' ' + hour + ':' + minute + ':' + second
		}
		if (type === 1) {
			return year + symbol + month + symbol + day
		}
		if (type === 2) {
			return hour + ':' + minute + ':' + second
		}
		if (type === 3) {
			return month + symbol + day + ' ' + hour + ':' + minute
		}
		if (type === 5) {
			return year + symbol + month + symbol + day + ' ' + hour + ':' + minute
		}
		if (type === 6) {
			return hour + ':' + minute
		}
		if (type === 7) {
			return year + symbol + month
		}
		// type === 4
		return year + symbol + month + symbol + day + ' ' + hour + ':' + minute + ':' + second + ':' + msec
	}
	return ''
}

/**
 * 得到时间戳
 * params：时间字符串、时间戳、时间对象
 */
const getTimestamp = (params) => {
	const date = dateFromOther(params)
	return new Date(date).getTime()
}

/**
 * 日期时间格式化

 * 1分钟内，显示刚刚
 * 1小时内，显示x分钟前
 * 1天内，显示时分
 * 1周内，显示星期x，时分
 * 1月内，显示月日时分
 * 1年内，显示月日时分
 * 超过1年，显示年月日
 */
const datetimeFormat = (datetime) => {
	if (datetime) {
		const current = Date.now()
		const res = {}
		const date = dateFromOther(datetime, res)
		const timestamp = new Date(date).getTime()
		const time = current - timestamp
		const {year, month, day, hour, minute, second, week} = res
		if (time > 365 * 24 * 60 * 60 * 1000) { // 超过一年
			return year + '年' + month + '月' + day + '日'
		}
		if (time > 7 * 24 * 60 * 60 * 1000) { // 1年以内，1周以外
			return month + '月' + day + '日' + ' ' + hour + ':' + minute
		}
		if (time > 24 * 60 * 60 * 1000) { // 1周以内，1天以外
			const arr = ['天', '一', '二', '三', '四', '五', '六']
			return '星期' + arr[week] + ' ' + hour + ':' + minute
		}
		if (time > 60 * 60 * 1000) { // 1天以内，1小时以外
			return hour + ':' + minute
		}
		if (time > 60 * 1000) { // 1小时以内，1分钟以外
			var temp = parseInt(time / 60000)
			if (temp * 60000 < time) {
				temp += 1
			}
			return temp + '分钟前'
		}
		if (time > 0) { // 1分钟以内
			return '刚刚'
		}
	}
	return datetime
}

// 获取当前时间阶段的名称
const getTimePeriod = () => {
	// 创建一个 Date 对象以获取当前时间
	const now = new Date(Date.now())
	// 获取当前时间的小时数
	const hour = now.getHours()
	var timePeriod = "您"
	if (hour > 0 && hour < 3) {
		timePeriod = "午夜"
	} else if (hour >= 3 && hour < 6) {
		timePeriod = "凌晨"
	} else if (hour >= 6 && hour < 9) {
		timePeriod = "早上"
	} else if (hour >= 9 && hour < 12) {
		timePeriod = "上午"
	} else if (hour >= 12 && hour < 14) {
		timePeriod = "中午"
	} else if (hour >= 14 && hour < 18) {
		timePeriod = "下午"
	} else if (hour >= 18 && hour < 23) {
		timePeriod = "晚上"
	} else if (hour >= 23) {
		timePeriod = "午夜"
	}
	return timePeriod
}

/**
 * 显示时间范围
 * times：前后两个时间
 * type：单个时间的显示格式
 * symbol：单个时间的年月日连接符
 * center：两个时间中间的符号
 */
const getRangeString = (times, type, symbol = '/', center = '~') => {
	if (times) {
		if (Array.isArray(times)) {
			if (times.length > 1) {
				return getString(times[0], type, symbol) + center + getString(times[1], type, symbol)
			}
			if (times.length === 1) {
				return getString(times[0], type, symbol)
			}
		}
		return getString(times, type, symbol)
	}
	return ''
}

/**
 * 获取星期几
 */
const getWeekDay = (params) => {
	const arr = ['日', '一', '二', '三', '四', '五', '六']
	const res = dateFromOther(params).getDay()
	return '星期' + arr[res]
}

/**
 * 公历转农历
 * params 时间字符串、时间戳、时间对象
 */
const lunarFromGregorian = (params = new Date()) => {
	const date = dateFromOther(params)
	let year = date.getFullYear(),
		month = date.getMonth() + 1,
		day = date.getDate()
	if (year && month && day) {
		const calendar = require('./calendar')
		return calendar.default.solar2lunar(year, month, day)
	}
	return null
}

/**
 * 农历转公历
 * dateString 日期的年月日字符串
 * isLeapMonth：是否闰月
 */
const gregorianFromLunar = (dateString, isLeapMonth) => {
	const date = dateFromOther(dateString)
	let year = date.getFullYear(),
		month = date.getMonth() + 1,
		day = date.getDate()
	if (year && month && day) {
		const calendar = require('./calendar')
		return calendar.default.lunar2solar(year, month, day, isLeapMonth)
	}
	return null
}

/**
 * 获取当天的开始结束时间
 * params：时间字符串、时间戳、时间对象
 * type：返回值格式：timestamp、string、date
 */
const rangeFromDay = (params = new Date(), type = 'timestamp') => {
	const date = dateFromOther(params)
	let year = date.getFullYear(),
		month = date.getMonth() + 1,
		day = date.getDate()
	const dayStr = `${year}/${month}/${day}`
	const start = dayStr + ' 00:00:00', end = dayStr + ' 23:59:59'
	if (type === 'string') {
		return [start, end]
	} else {
		const startstamp = new Date(start).getTime()
		const endstamp = startstamp + 24 * 60 * 60 * 1000 - 1
		if (type === 'timestamp') {
			return [startstamp, endstamp]
		}
		return [new Date(startstamp), new Date(endstamp)]
	}
}

/**
 * 获取所在周的开始结束时间
 * params：时间字符串、时间戳、时间对象
 * type：返回值格式：timestamp、string、date
 * bool：true每周从星期一开始；false每周从星期日开始
 */
const rangeFromWeek = (params = new Date(), type = 'timestamp', bool) => {
	const date = dateFromOther(params)
	let year = date.getFullYear(),
		month = date.getMonth() + 1,
		day = date.getDate(),
		week = date.getDay()
	const dayStr = `${year}/${month}/${day} 00:00:00`
	const timestamp = new Date(dayStr).getTime()
	const startstamp = timestamp - (week - (bool ? 1 : 0)) * 24 * 60 * 60 * 1000
	const endstamp = startstamp + 7 * 24 * 60 * 60 * 1000 - 1
	if (type === 'string') {
		const start = new Date(startstamp), end = new Date(endstamp)
		return [`${start.getFullYear()}/${start.getMonth() + 1}/${start.getDate()}`, `${end.getFullYear()}/${end.getMonth() + 1}/${end.getDate()}`]
	} else {
		if (type === 'timestamp') {
			return [startstamp, endstamp]
		}
		return [new Date(startstamp), new Date(endstamp)]
	}
}

/**
 * 获取所在月的开始结束时间
 * params：时间字符串、时间戳、时间对象
 * type：返回值格式：timestamp、string、date
 */
const rangeFromMonth = (params = new Date(), type = 'timestamp') => {
	const date = dateFromOther(params)
	let year = date.getFullYear(),
		month = date.getMonth() + 1,
		day = date.getDate()
	const monthStr = `${year}/${month}`
	const start = monthStr + '/1 00:00:00'
	const end = month === 12 ? `${year + 1}/1/1 00:00:00` : `${year}/${month + 1}/1 00:00:00`
	const endstamp = new Date(end).getTime() - 1
	const enddate = new Date(endstamp)
	if (type === 'string') {
		return [start, `${enddate.getFullYear()}/${enddate.getMonth() + 1}/${enddate.getDate()}`]
	} else {
		if (type === 'timestamp') {
			return [new Date(start).getTime(), endstamp]
		}
		return [new Date(start), enddate]
	}
}

/**
 * 获取所在年的开始结束时间
 * params：时间字符串、时间戳、时间对象
 * type：返回值格式：timestamp、string、date
 */
const rangeFromYear = (params = new Date(), type = 'timestamp') => {
	const date = dateFromOther(params)
	let year = date.getFullYear(),
		month = date.getMonth() + 1,
		day = date.getDate()
	const start = `${year}/1/1 00:00:00`
	const end = `${year}/12/31 23:59:59`
	if (type === 'string') {
		return [start, end]
	} else {
		const startstamp = new Date(start).getTime()
		const endstamp = new Date(end).getTime() + 999
		if (type === 'timestamp') {
			return [startstamp, endstamp]
		}
		return [new Date(startstamp), new Date(endstamp)]
	}
}

/**
 * 获取相邻的时间范围
 * params：当前日期。字符串、时间戳、对象都可以
 * current：0日；1周；2月；3年
 * isLast：true是上一个；false为下一个
 * type：返回值格式：timestamp、string、date
 * return {
	 range：时间范围
	 result：结果时间。根据type得到不同的格式
 }
 */
const theCloseDate = (params, current, isLast, type = 'timestamp') => {
	const obj = {}
	const date = dateFromOther(params, obj)
	var range, result
	switch (current){
		case 0: // 日
		{
			// 转为时间戳，好计算
			let timestamp = new Date(date).getTime()
			if (isLast) {
				timestamp -= 24 * 60 * 60 * 1000
			} else {
				timestamp += 24 * 60 * 60 * 1000
			}
			range = rangeFromDay(timestamp, type)
			result = getResult(timestamp, type)
		}
			break
		case 1: // 周
		{
			// 转为时间戳，好计算
			let timestamp = new Date(date).getTime()
			if (isLast) {
				timestamp -= 7 * 24 * 60 * 60 * 1000
			} else {
				timestamp += 7 * 24 * 60 * 60 * 1000
			}
			range = rangeFromWeek(timestamp, type)
			result = getResult(timestamp, type)
		}
			break
		case 2: // 月
		{
			let {year, month, day, hour, minute, second, msec} = obj
			year = parseInt(year)
			month = parseInt(month)
			day = parseInt(day)
			// 月份直接加减1 年份对应变化
			if (isLast) {
				if (month === 1) {
					year -= 1
					month = 12
				} else {
					month -= 1
				}
			} else {
				if (month === 12) {
					year += 1
					month = 1
				} else {
					month += 1
				}
			}
			if (day === 31) {
				if (month === 2) {
					day = isLeap(year) ? 29 :28
				} else if (month === 1 || month === 3 || month === 5 || month === 7 || month === 8 || month === 10 || month === 12) {
					// 大月不变
				} else {
					// 小月最后一天变为30
					day = 30
				}
			} else if (day === 30) {
				if (month === 2) {
					day = isLeap(year) ? 29 :28
				}
			} else if (day === 29) {
				if (month === 2) {
					day = isLeap(year) ? 29 :28
				}
			}
			const str = `${year}/${month}/${day} ${hour}:${minute}:${second}:${msec}`
			range = rangeFromMonth(str, type)
			result = getResult(str, type)
		}
			break
		case 3: // 年
		{
			let year = date.getFullYear(),
				month = date.getMonth() + 1,
				day = date.getDate()
			const str = `${isLast ? (year - 1) : (year + 1)}/${month}/${day} ${hour}:${minute}:${second}:${msec}`
			range = rangeFromMonth(str, type)
			result = getResult(str, type)
		}
			break
		default:
			break
	}
	return {range, result}
}

/**
 * 判断是不是闰年
 */
const isLeap = (year) => {
	if ((year % 4 === 0 && year % 100 > 0) || year % 400 === 0) {
		return true
	}
	return false
}

/**
 * 将秒时间转化为时分秒
 * 先四舍五入得到整秒数
 */
const timeString = (second) => {
	var t1, t2, t3, str = '00:00' // 分别是秒数、分数、时数
	if (second) {
		second = Math.round(parseFloat(second))
		t1 = second % 60
		if (second > 59) {
			t2 = parseInt(second / 60)
			if (t2 > 59) {
				t2 = t2 % 60
				t3 = parseInt(second / 60 / 60)
			}
		}
		if (t1 < 10) {
			t1 = '0' + t1
		}
		if (t2) {
			if (t2 < 10) {
				t2 = '0' + t2
			}
			str = t2 + ':' + t1
		} else {
			str = '00:' + t1
		}
		if (t3) {
			str = t3 + ':' + str
		}
	}
	return str
}

module.exports = {
	dateFromOther,
	getString,
	getRangeString,
	getTimestamp,
	getWeekDay,
	getTimePeriod,
	datetimeFormat,
	
	lunarFromGregorian,
	gregorianFromLunar,
	rangeFromDay,
	rangeFromWeek,
	rangeFromMonth,
	rangeFromYear,
	theCloseDate,
	isLeap,
	timeString
}